package UI.Loader
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.filesystem.*;
	import flash.net.*;
	
	public class SkinLoader
	{
		private const SKINS_PATH:String = File.applicationDirectory.resolvePath("Skins").url;
		
		private static var skinLoader:SkinLoader;
		private var bitmapLookup:Object;
		
		public function SkinLoader(accessKey:int)
		{
			if(accessKey!=1989623)
				throw new Error("SkinLoader(): Access Denied: use init() instead");
			bitmapLookup=new Object();
		}
		
		static public function init():SkinLoader
		{
			if(skinLoader==null)
				skinLoader = new SkinLoader(1989623);
			return skinLoader;
		}
		
		public function retrieveClassAssets(className:String):Object
		{
			if(!this.preloadComplete)
				throw new Error("SkinLoader: retrieveClassAssets(1) can only be called after preload() function completes!");
			var obj:Object=new Object();
			var dir:File = new File(SKINS_PATH+File.separator+className);
			for each(var f:File in dir.getDirectoryListing())
			{
				var dirArr:Array = f.url.split(File.separator);
				var objectName:String = dirArr[dirArr.length-1].substring(0,dirArr[dirArr.length-1].length-4);
				obj[objectName] = bitmapLookup[f.url];
			}
			return obj;
		}
		
		private static var getBitmapCallback:Function=null;
		private var queue:Vector.<Object> = new Vector.<Object>();
		private var lock:Boolean=false;
		private function getBitmap(bitmapName:String,callback:Function):void
		{
			var url:String = SKINS_PATH+File.separator+bitmapName+".png";
			if(lock)
			{
				queue.push({bitmapName:bitmapName,callback:callback});	
				return;
			}
			else
				lock=true;
			if(bitmapLookup[url]!=null)
			{
				callback(bitmapLookup[url]);
				lock=false;
				return;
			}
			getBitmapCallback=callback;
			var l:Loader = new Loader();
			l.contentLoaderInfo.addEventListener(Event.COMPLETE, bitmapLoaded);
			l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,bitmapLoadError);
 			l.load(new URLRequest(url));
		}
		
		private var preloadCallback:Function = null;
		private var preloadDirLength:int=0;
		private var preloadCalled:Boolean=false;
		private var preloadComplete:Boolean=false;
		public function preload(callback:Function):void
		{
			if(preloadCalled)
			{
				if(preloadComplete)
					callback();
				return;
			}
			preloadCalled=true;
			preloadCallback = callback;
			var dir:File = new File(SKINS_PATH);
			loadFilesFromDir(dir,preloadCheckForFinish);
		}
		
		private function loadFilesFromDir(dir:File,callback:Function):void
		{
			var dirListing:Array = dir.getDirectoryListing();
			for each(var f:File in dirListing)
			{
				if(f.isDirectory)
				{
					loadFilesFromDir(f,callback);
					continue;
				}
				++preloadDirLength;
				var bitmapName:String = f.url.substring(SKINS_PATH.length+1,f.url.length-4);
				getBitmap(bitmapName,callback);
			}
		}
		
		private function preloadCheckForFinish(b:Bitmap):void
		{
			--preloadDirLength;
			if(preloadDirLength==0)
			{
				preloadComplete=true;
				preloadCallback();
			}
		}
		
		private function bitmapLoaded(e:Event):void
		{
			e.target.removeEventListener(Event.COMPLETE, bitmapLoaded);
			
			bitmapLookup[e.target.url] = e.target.content;
			
			getBitmapCallback(e.target.content);
			getBitmapCallback=null;
			
			lock=false;
			checkQueue();
		}
		
		private function bitmapLoadError(e:IOErrorEvent):void
		{
			e.target.removeEventListener(IOErrorEvent.IO_ERROR,bitmapLoadError);
			
			getBitmapCallback(null);
			getBitmapCallback=null;
			
			lock=false;
			checkQueue();
		}
		
		private function checkQueue():void
		{
			var obj:Object = queue.pop();
			if(obj!=null)
				getBitmap(obj.bitmapName,obj.callback);
		}
	}
}